#pragma once

#include <GdiPlus.h>

#include "Graph/Graphics.h"

namespace g2 = Gdiplus;
class g2::Graphics;

class Win32Graphics : public Graphics
{
public:
	Win32Graphics();
	~Win32Graphics();

	virtual GraphicsSurface* GetGraphicsSurface() const;
	virtual bool Create(GraphicsSurface* surface,float scale=1.0f);
	virtual void ClearColor(const Color& color);

	virtual void SetPageScale(float scale);
	virtual float GetPageScale() const;
	virtual float GetDpiX() const;
	virtual float GetDpiY() const;

	virtual void ResetTransform();
	virtual void SetTransform(const Matrix& matrix);
	virtual void MultiplyTransform(const Matrix& matrix,Matrix::matrixOrder order=Matrix::prependOrder);
	virtual void TranslateTransform(float dx,float dy,Matrix::matrixOrder order=Matrix::prependOrder);
	virtual void ScaleTransform(float sx,float sy,Matrix::matrixOrder order=Matrix::prependOrder);
	virtual void RotateTransform(float angle,Matrix::matrixOrder order=Matrix::prependOrder);
	virtual Matrix GetTransform() const;

	virtual Point CoordinateDeviceToWorld(const Point& pt) const;
	virtual Point CoordinateWorldToDevice(const Point& pt) const;
	virtual Rect CoordinateDeviceToWorld(const Rect& rect) const;
	virtual Rect CoordinateWorldToDevice(const Rect& rect) const;
	virtual Size CoordinateDeviceToWorld(const Size& size) const;
	virtual Size CoordinateWorldToDevice(const Size& size) const;

	virtual float UnitMMtoLine(float value);
	virtual float UnitInchtoLine(float value);
	virtual float UnitCMtoLine(float value);
	virtual float UnitLinetoMM(float value);
	virtual float UnitLinetoCM(float value);
	virtual float UnitLinetoInch(float value);

	virtual void DrawLine(const Pen& pen,const Point& pt1,const Point& pt2);
	virtual void DrawLines(const Pen& pen,const Points& pts);
	virtual void DrawRectangle(const Pen& pen,const Point& pt1,const Point& pt2);
	virtual void DrawRectangle(const Pen& pen,float x,float y,float width,float height);
	virtual void DrawRectangle(const Pen& pen,const Rect& rc);
	virtual void DrawRectangles(const Pen& pen,const Rects& rects);
	virtual void DrawEllipse(const Pen& pen,const Rect& rc);
	virtual void DrawPolygon(const Pen& pen,const Points& pts);	

	virtual void DrawArc(const Pen& pen,float x,float y,float width,float height,float startAngle,float sweepAngle);
	virtual void DrawArc(const Pen& pen,const Rect& rc,float startAngle,float sweepAngle);
	virtual void DrawPie(const Pen& pen,const Rect& rc,float startAngle,float sweepAngle);
	virtual void DrawCurve(const Pen& pen,const Points& pts,bool closed=false);
	virtual void DrawCurve(const Pen& pen,const Points& pts,float tension,bool closed=false);
	virtual void DrawCurve(const Pen& pen,const Points& pts,int offset,int numberOfSegments,float tension = 0.5f);
	virtual void DrawBezier(const Pen& pen,const Point& pt1,const Point& pt2,const Point& pt3,const Point& pt4);
	virtual void DrawBeziers(const Pen& pen,const Points& pts);
	virtual void DrawImage(const Image& image,const Rect& rect);

	virtual void FillRectangle(const Brush& brush,const Rect& rect);
	virtual void FillRectangle(const Brush& brush,float x,float y,float width,float height);
	virtual void FillRectangle(const Brush& brush,const Point& pt1,const Size& size);
	virtual void FillRectangles(const Brush& brush,const Rects& rects);
	virtual void FillPolygon(const Brush& brush,const Points& pts);
	virtual void FillPolygon(const Brush& brush,const Points& pts,fillMode fill);
	virtual void FillEllipse(const Brush& brush,const Rect& rect);
	virtual void FillPie(const Brush& brush,const Rect& rect,float startAngle,float sweepAngle);
	virtual void FillClosedCurve(const Brush& brush,const Points& pts);
	virtual void FillClosedCurve(const Brush& brush,const Points& pts,fillMode fill,float tension=0.5f);

	virtual void DrawText(const String& string,const Point& origin);
private:
	g2::MatrixOrder Tog2MatrixOrder(Matrix::matrixOrder order);
	g2::PointF* Tog2Points(const Points& pts);
	g2::RectF* Tog2Rects(const Rects& rects);
	g2::Color Tog2Color(const Color& color);
	g2::Pen* Tog2Pen(const Pen& pen);
	g2::Brush* Tog2Brush(const Brush& brush);
	g2::LineCap Tog2LineCap(lineCap cap);
	g2::DashCap Tog2DashCap(dashCap cap);
	g2::FillMode Tog2FillMode(fillMode fill);

	g2::Graphics* m_graphics;
	GraphicsSurface* m_surface;
};